if (window.Range && !Range.prototype.movePoint) {
  if (Range.prototype.__defineGetter__) {
    Range.prototype.__defineGetter__('text', function() {
      return this.toString()
    });
    Range.prototype.__defineSetter__('text', function(a) {
      this.deleteContents()
      this.insertNode(document.createTextNode(a))
    });
  }
  Range.prototype.movePoint = function(a, b) {
    var c = this.startContainer.firstChild || this.startContainer,
      d, i = a,
      l = 0,
      b = b == null ? a : b;
    do {
      this.selectNodeContents(c);
      l = this.toString().length;
      i -= l;
    } while (i > 0 && (c = c.nextSibling));
    c = d = this.startContainer;
    i += l;
    var j = b - a + i,
      l = 0;
    do {
      this.selectNodeContents(d);
      l = this.toString().length;
      j -= l;
    } while (j > 0 && (d = d.nextSibling));
    this.setStart(c.firstChild || c, i);
    if (d) {
      var e = d;
      while (e.firstChild) e = e.firstChild;
      this.setEnd(e, l + j);
    }
  };
  Range.prototype.select = function() {
    let s = window.getSelection()
    s.removeAllRanges()
    s.addRange(this)
  };
}

const rngSelection = function() {
  let s = window.getSelection()
  return s.rangeCount && s.getRangeAt(0)
}
const rngElement = function() {
  let s = rngSelection()
  return s && s.startContainer.parentNode
}
const rngCursor = function(a, b) {
  let r = a
  if (window.getSelection) {
    if (typeof a.selectionStart === 'number' && typeof a.selectionEnd === 'number') {
      a.selectionStart = a.selectionEnd = b != null ? b : a.value.length
    } else {
      let s = window.getSelection()
      if (a.nodeType === 1)
        (r = document.createRange()).selectNodeContents(a)
      if (b != null)
        r.movePoint(b)
      s.removeAllRanges()
      s.addRange(r)
      s.collapseToEnd()
    }
  }
  return r
}
const rngCursorOffset = function() {
  let n = rngSelection()
  let c = n.startOffset
  if (c != null)
    return c
  let r = document.body.createTextRange()
  r.selectNodeContents(n.startContainer.parentNode)
  r.setEndPoint('EndToStart', n)
  return rngText(r).length
}
// @a ->range, b -> text?
const rngText = function(a, b) {
  if (a == null)
    a = rngSelection()
  if (b != null) {
    if (a.deleteContents) {
      a.deleteContents()
      a.insertNode(document.createTextNode(b))
    } else {
      a.text = b
    }
  }
  return a.text === undefined ? a.toString() : a.text
}

export {
  rngSelection,
  rngElement,
  rngCursor,
  rngCursorOffset,
  rngText
}
